/* do not edit automatically generated by mc from StringConvert.  */
/* StringConvert.mod provides functions to convert numbers to and from strings.

Copyright (C) 2001-2023 Free Software Foundation, Inc.
Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.

This file is part of GNU Modula-2.

GNU Modula-2 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.

GNU Modula-2 is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.

You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
<http://www.gnu.org/licenses/>.  */

#include "config.h"
#include "system.h"
#include <stdbool.h>
#   if !defined (PROC_D)
#      define PROC_D
       typedef void (*PROC_t) (void);
       typedef struct { PROC_t proc; } PROC;
#   endif

#   if !defined (TRUE)
#      define TRUE (1==1)
#   endif

#   if !defined (FALSE)
#      define FALSE (1==0)
#   endif

#if defined(__cplusplus)
#   undef NULL
#   define NULL 0
#endif
#define _StringConvert_H
#define _StringConvert_C

#   include "GSYSTEM.h"
#   include "Glibc.h"
#   include "Glibm.h"
#   include "GM2RTS.h"
#   include "GDynamicStrings.h"
#   include "Gldtoa.h"
#   include "Gdtoa.h"


/*
   IntegerToString - converts INTEGER, i, into a String. The field with can be specified
                     if non zero. Leading characters are defined by padding and this
                     function will prepend a + if sign is set to TRUE.
                     The base allows the caller to generate binary, octal, decimal, hexidecimal
                     numbers. The value of lower is only used when hexidecimal numbers are
                     generated and if TRUE then digits abcdef are used, and if FALSE then ABCDEF
                     are used.
*/

extern "C" DynamicStrings_String StringConvert_IntegerToString (int i, unsigned int width, char padding, bool sign, unsigned int base, bool lower);

/*
   CardinalToString - converts CARDINAL, c, into a String. The field with can be specified
                      if non zero. Leading characters are defined by padding.
                      The base allows the caller to generate binary, octal, decimal, hexidecimal
                      numbers. The value of lower is only used when hexidecimal numbers are
                      generated and if TRUE then digits abcdef are used, and if FALSE then ABCDEF
                      are used.
*/

extern "C" DynamicStrings_String StringConvert_CardinalToString (unsigned int c, unsigned int width, char padding, unsigned int base, bool lower);

/*
   StringToInteger - converts a string, s, of, base, into an INTEGER.
                     Leading white space is ignored. It stops converting
                     when either the string is exhausted or if an illegal
                     numeral is found.
                     The parameter found is set TRUE if a number was found.
*/

extern "C" int StringConvert_StringToInteger (DynamicStrings_String s, unsigned int base, bool *found);

/*
   StringToCardinal - converts a string, s, of, base, into a CARDINAL.
                      Leading white space is ignored. It stops converting
                      when either the string is exhausted or if an illegal
                      numeral is found.
                      The parameter found is set TRUE if a number was found.
*/

extern "C" unsigned int StringConvert_StringToCardinal (DynamicStrings_String s, unsigned int base, bool *found);

/*
   LongIntegerToString - converts LONGINT, i, into a String. The field with
                         can be specified if non zero. Leading characters
                         are defined by padding and this function will
                         prepend a + if sign is set to TRUE.
                         The base allows the caller to generate binary,
                         octal, decimal, hexidecimal numbers.
                         The value of lower is only used when hexidecimal
                         numbers are generated and if TRUE then digits
                         abcdef are used, and if FALSE then ABCDEF are used.
*/

extern "C" DynamicStrings_String StringConvert_LongIntegerToString (long int i, unsigned int width, char padding, bool sign, unsigned int base, bool lower);

/*
   StringToLongInteger - converts a string, s, of, base, into an LONGINT.
                         Leading white space is ignored. It stops converting
                         when either the string is exhausted or if an illegal
                         numeral is found.
                         The parameter found is set TRUE if a number was found.
*/

extern "C" long int StringConvert_StringToLongInteger (DynamicStrings_String s, unsigned int base, bool *found);

/*
   LongCardinalToString - converts LONGCARD, c, into a String. The field
                          width can be specified if non zero. Leading
                          characters are defined by padding.
                          The base allows the caller to generate binary,
                          octal, decimal, hexidecimal numbers.
                          The value of lower is only used when hexidecimal
                          numbers are generated and if TRUE then digits
                          abcdef are used, and if FALSE then ABCDEF are used.
*/

extern "C" DynamicStrings_String StringConvert_LongCardinalToString (long unsigned int c, unsigned int width, char padding, unsigned int base, bool lower);

/*
   StringToLongCardinal - converts a string, s, of, base, into a LONGCARD.
                          Leading white space is ignored. It stops converting
                          when either the string is exhausted or if an illegal
                          numeral is found.
                          The parameter found is set TRUE if a number was found.
*/

extern "C" long unsigned int StringConvert_StringToLongCardinal (DynamicStrings_String s, unsigned int base, bool *found);

/*
   ShortCardinalToString - converts SHORTCARD, c, into a String. The field
                          width can be specified if non zero. Leading
                          characters are defined by padding.
                          The base allows the caller to generate binary,
                          octal, decimal, hexidecimal numbers.
                          The value of lower is only used when hexidecimal
                          numbers are generated and if TRUE then digits
                          abcdef are used, and if FALSE then ABCDEF are used.
*/

extern "C" DynamicStrings_String StringConvert_ShortCardinalToString (short unsigned int c, unsigned int width, char padding, unsigned int base, bool lower);

/*
   StringToShortCardinal - converts a string, s, of, base, into a SHORTCARD.
                           Leading white space is ignored. It stops converting
                           when either the string is exhausted or if an illegal
                           numeral is found.
                           The parameter found is set TRUE if a number was found.
*/

extern "C" short unsigned int StringConvert_StringToShortCardinal (DynamicStrings_String s, unsigned int base, bool *found);

/*
   stoi - decimal string to INTEGER
*/

extern "C" int StringConvert_stoi (DynamicStrings_String s);

/*
   itos - integer to decimal string.
*/

extern "C" DynamicStrings_String StringConvert_itos (int i, unsigned int width, char padding, bool sign);

/*
   ctos - cardinal to decimal string.
*/

extern "C" DynamicStrings_String StringConvert_ctos (unsigned int c, unsigned int width, char padding);

/*
   stoc - decimal string to CARDINAL
*/

extern "C" unsigned int StringConvert_stoc (DynamicStrings_String s);

/*
   hstoi - hexidecimal string to INTEGER
*/

extern "C" int StringConvert_hstoi (DynamicStrings_String s);

/*
   ostoi - octal string to INTEGER
*/

extern "C" int StringConvert_ostoi (DynamicStrings_String s);

/*
   bstoi - binary string to INTEGER
*/

extern "C" int StringConvert_bstoi (DynamicStrings_String s);

/*
   hstoc - hexidecimal string to CARDINAL
*/

extern "C" unsigned int StringConvert_hstoc (DynamicStrings_String s);

/*
   ostoc - octal string to CARDINAL
*/

extern "C" unsigned int StringConvert_ostoc (DynamicStrings_String s);

/*
   bstoc - binary string to CARDINAL
*/

extern "C" unsigned int StringConvert_bstoc (DynamicStrings_String s);

/*
   StringToLongreal - returns a LONGREAL and sets found to TRUE if a legal number is seen.
*/

extern "C" long double StringConvert_StringToLongreal (DynamicStrings_String s, bool *found);

/*
   LongrealToString - converts a LONGREAL number, Real, which has,
                      TotalWidth, and FractionWidth into a string.
                      It uses decimal notation.

                      So for example:

                      LongrealToString(1.0, 4, 2)  -> '1.00'
                      LongrealToString(12.3, 5, 2) -> '12.30'
                      LongrealToString(12.3, 6, 2) -> ' 12.30'
                      LongrealToString(12.3, 6, 3) -> '12.300'

                      if total width is too small then the fraction
                      becomes truncated.

                      LongrealToString(12.3, 5, 3) -> '12.30'

                      Positive numbers do not have a '+' prepended.
                      Negative numbers will have a '-' prepended and
                      the TotalWidth will need to be large enough
                      to contain the sign, whole number, '.' and
                      fractional components.
*/

extern "C" DynamicStrings_String StringConvert_LongrealToString (long double x, unsigned int TotalWidth, unsigned int FractionWidth);

/*
   stor - returns a REAL given a string.
*/

extern "C" double StringConvert_stor (DynamicStrings_String s);

/*
   stolr - returns a LONGREAL given a string.
*/

extern "C" long double StringConvert_stolr (DynamicStrings_String s);

/*
   ToSigFig - returns a floating point or base 10 integer
              string which is accurate to, n, significant
              figures.  It will return a new String
              and, s, will be destroyed.


              So:  12.345

              rounded to the following significant figures yields

              5      12.345
              4      12.34
              3      12.3
              2      12
              1      10
*/

extern "C" DynamicStrings_String StringConvert_ToSigFig (DynamicStrings_String s, unsigned int n);

/*
   ToDecimalPlaces - returns a floating point or base 10 integer
                     string which is accurate to, n, decimal
                     places.  It will return a new String
                     and, s, will be destroyed.
                     Decimal places yields, n, digits after
                     the .

                     So:  12.345

                     rounded to the following decimal places yields

                     5      12.34500
                     4      12.3450
                     3      12.345
                     2      12.34
                     1      12.3
*/

extern "C" DynamicStrings_String StringConvert_ToDecimalPlaces (DynamicStrings_String s, unsigned int n);

/*
   Assert - implement a simple assert.
*/

static void Assert (bool b, const char *file_, unsigned int _file_high, unsigned int line, const char *func_, unsigned int _func_high);

/*
   Max -
*/

static unsigned int Max (unsigned int a, unsigned int b);

/*
   Min -
*/

static unsigned int Min (unsigned int a, unsigned int b);

/*
   LongMin - returns the smallest LONGCARD
*/

static long unsigned int LongMin (long unsigned int a, long unsigned int b);

/*
   IsDigit - returns TRUE if, ch, lies between '0'..'9'.
*/

static bool IsDigit (char ch);

/*
   IsDecimalDigitValid - returns the TRUE if, ch, is a base legal decimal digit.
                         If legal then the value is appended numerically onto, c.
*/

static bool IsDecimalDigitValid (char ch, unsigned int base, unsigned int *c);

/*
   IsHexidecimalDigitValid - returns the TRUE if, ch, is a base legal hexidecimal digit.
                             If legal then the value is appended numerically onto, c.
*/

static bool IsHexidecimalDigitValid (char ch, unsigned int base, unsigned int *c);

/*
   IsDecimalDigitValidLong - returns the TRUE if, ch, is a base legal decimal digit.
                             If legal then the value is appended numerically onto, c.
*/

static bool IsDecimalDigitValidLong (char ch, unsigned int base, long unsigned int *c);

/*
   IsHexidecimalDigitValidLong - returns the TRUE if, ch, is a base legal hexidecimal digit.
                                 If legal then the value is appended numerically onto, c.
*/

static bool IsHexidecimalDigitValidLong (char ch, unsigned int base, long unsigned int *c);

/*
   IsDecimalDigitValidShort - returns the TRUE if, ch, is a base legal decimal digit.
                              If legal then the value is appended numerically onto, c.
*/

static bool IsDecimalDigitValidShort (char ch, unsigned int base, short unsigned int *c);

/*
   IsHexidecimalDigitValidShort - returns the TRUE if, ch, is a base legal hexidecimal digit.
                                  If legal then the value is appended numerically onto, c.
*/

static bool IsHexidecimalDigitValidShort (char ch, unsigned int base, short unsigned int *c);

/*
   ToThePower10 - returns a LONGREAL containing the value of v * 10^power.
*/

static long double ToThePower10 (long double v, int power);

/*
   DetermineSafeTruncation - we wish to use TRUNC when converting REAL/LONGREAL
                             into a string for the non fractional component.
                             However we need a simple method to
                             determine the maximum safe truncation value.
*/

static unsigned int DetermineSafeTruncation (void);

/*
   rtos -
*/

static DynamicStrings_String rtos (double r, unsigned int TotalWidth, unsigned int FractionWidth);

/*
   lrtos -
*/

static DynamicStrings_String lrtos (long double r, unsigned int TotalWidth, unsigned int FractionWidth);

/*
   doDecimalPlaces - returns a string which is accurate to
                     n decimal places.  It returns a new String
                     and, s, will be destroyed.
*/

static DynamicStrings_String doDecimalPlaces (DynamicStrings_String s, unsigned int n);

/*
   doSigFig - returns a string which is accurate to
              n decimal places.  It returns a new String
              and, s, will be destroyed.
*/

static DynamicStrings_String doSigFig (DynamicStrings_String s, unsigned int n);

/*
   carryOne - add a carry at position, i.
*/

static DynamicStrings_String carryOne (DynamicStrings_String s, unsigned int i);


/*
   Assert - implement a simple assert.
*/

static void Assert (bool b, const char *file_, unsigned int _file_high, unsigned int line, const char *func_, unsigned int _func_high)
{
  char file[_file_high+1];
  char func[_func_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (file, file_, _file_high+1);
  memcpy (func, func_, _func_high+1);

  if (! b)
    {
      M2RTS_ErrorMessage ((const char *) "assert failed", 13, (const char *) file, _file_high, line, (const char *) func, _func_high);
    }
}


/*
   Max -
*/

static unsigned int Max (unsigned int a, unsigned int b)
{
  if (a > b)
    {
      return a;
    }
  else
    {
      return b;
    }
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   Min -
*/

static unsigned int Min (unsigned int a, unsigned int b)
{
  if (a < b)
    {
      return a;
    }
  else
    {
      return b;
    }
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   LongMin - returns the smallest LONGCARD
*/

static long unsigned int LongMin (long unsigned int a, long unsigned int b)
{
  if (a < b)
    {
      return a;
    }
  else
    {
      return b;
    }
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   IsDigit - returns TRUE if, ch, lies between '0'..'9'.
*/

static bool IsDigit (char ch)
{
  return (ch >= '0') && (ch <= '9');
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   IsDecimalDigitValid - returns the TRUE if, ch, is a base legal decimal digit.
                         If legal then the value is appended numerically onto, c.
*/

static bool IsDecimalDigitValid (char ch, unsigned int base, unsigned int *c)
{
  if ((IsDigit (ch)) && (( ((unsigned int) (ch))- ((unsigned int) ('0'))) < base))
    {
      (*c) = ((*c)*base)+( ((unsigned int) (ch))- ((unsigned int) ('0')));
      return true;
    }
  else
    {
      return false;
    }
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   IsHexidecimalDigitValid - returns the TRUE if, ch, is a base legal hexidecimal digit.
                             If legal then the value is appended numerically onto, c.
*/

static bool IsHexidecimalDigitValid (char ch, unsigned int base, unsigned int *c)
{
  if (((ch >= 'a') && (ch <= 'f')) && ((( ((unsigned int) (ch))- ((unsigned int) ('a')))+10) < base))
    {
      (*c) = ((*c)*base)+(( ((unsigned int) (ch))- ((unsigned int) ('a')))+10);
      return true;
    }
  else if (((ch >= 'A') && (ch <= 'F')) && ((( ((unsigned int) (ch))- ((unsigned int) ('F')))+10) < base))
    {
      /* avoid dangling else.  */
      (*c) = ((*c)*base)+(( ((unsigned int) (ch))- ((unsigned int) ('A')))+10);
      return true;
    }
  else
    {
      /* avoid dangling else.  */
      return false;
    }
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   IsDecimalDigitValidLong - returns the TRUE if, ch, is a base legal decimal digit.
                             If legal then the value is appended numerically onto, c.
*/

static bool IsDecimalDigitValidLong (char ch, unsigned int base, long unsigned int *c)
{
  if ((IsDigit (ch)) && (( ((unsigned int) (ch))- ((unsigned int) ('0'))) < base))
    {
      (*c) = (*c)*((long unsigned int ) (base+( ((unsigned int) (ch))- ((unsigned int) ('0')))));
      return true;
    }
  else
    {
      return false;
    }
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   IsHexidecimalDigitValidLong - returns the TRUE if, ch, is a base legal hexidecimal digit.
                                 If legal then the value is appended numerically onto, c.
*/

static bool IsHexidecimalDigitValidLong (char ch, unsigned int base, long unsigned int *c)
{
  if (((ch >= 'a') && (ch <= 'f')) && ((( ((unsigned int) (ch))- ((unsigned int) ('a')))+10) < base))
    {
      (*c) = (*c)*((long unsigned int ) (base+(( ((unsigned int) (ch))- ((unsigned int) ('a')))+10)));
      return true;
    }
  else if (((ch >= 'A') && (ch <= 'F')) && ((( ((unsigned int) (ch))- ((unsigned int) ('F')))+10) < base))
    {
      /* avoid dangling else.  */
      (*c) = (*c)*((long unsigned int ) (base+(( ((unsigned int) (ch))- ((unsigned int) ('A')))+10)));
      return true;
    }
  else
    {
      /* avoid dangling else.  */
      return false;
    }
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   IsDecimalDigitValidShort - returns the TRUE if, ch, is a base legal decimal digit.
                              If legal then the value is appended numerically onto, c.
*/

static bool IsDecimalDigitValidShort (char ch, unsigned int base, short unsigned int *c)
{
  if ((IsDigit (ch)) && (( ((unsigned int) (ch))- ((unsigned int) ('0'))) < base))
    {
      (*c) = (*c)*((short unsigned int ) (base+( ((unsigned int) (ch))- ((unsigned int) ('0')))));
      return true;
    }
  else
    {
      return false;
    }
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   IsHexidecimalDigitValidShort - returns the TRUE if, ch, is a base legal hexidecimal digit.
                                  If legal then the value is appended numerically onto, c.
*/

static bool IsHexidecimalDigitValidShort (char ch, unsigned int base, short unsigned int *c)
{
  if (((ch >= 'a') && (ch <= 'f')) && ((( ((unsigned int) (ch))- ((unsigned int) ('a')))+10) < base))
    {
      (*c) = (*c)*((short unsigned int ) (base+(( ((unsigned int) (ch))- ((unsigned int) ('a')))+10)));
      return true;
    }
  else if (((ch >= 'A') && (ch <= 'F')) && ((( ((unsigned int) (ch))- ((unsigned int) ('F')))+10) < base))
    {
      /* avoid dangling else.  */
      (*c) = (*c)*((short unsigned int ) (base+(( ((unsigned int) (ch))- ((unsigned int) ('A')))+10)));
      return true;
    }
  else
    {
      /* avoid dangling else.  */
      return false;
    }
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   ToThePower10 - returns a LONGREAL containing the value of v * 10^power.
*/

static long double ToThePower10 (long double v, int power)
{
  int i;

  i = 0;
  if (power > 0)
    {
      while (i < power)
        {
          v = v*10.0;
          i += 1;
        }
    }
  else
    {
      while (i > power)
        {
          v = v/10.0;
          i -= 1;
        }
    }
  return v;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   DetermineSafeTruncation - we wish to use TRUNC when converting REAL/LONGREAL
                             into a string for the non fractional component.
                             However we need a simple method to
                             determine the maximum safe truncation value.
*/

static unsigned int DetermineSafeTruncation (void)
{
  double MaxPowerOfTen;
  unsigned int LogPower;

  MaxPowerOfTen = static_cast<double> (1.0);
  LogPower = 0;
  while ((MaxPowerOfTen*10.0) < ((double) ((INT_MAX) / 10)))
    {
      MaxPowerOfTen = MaxPowerOfTen*10.0;
      LogPower += 1;
    }
  return LogPower;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   rtos -
*/

static DynamicStrings_String rtos (double r, unsigned int TotalWidth, unsigned int FractionWidth)
{
  M2RTS_HALT (-1);
  __builtin_unreachable ();
  return static_cast<DynamicStrings_String> (NULL);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   lrtos -
*/

static DynamicStrings_String lrtos (long double r, unsigned int TotalWidth, unsigned int FractionWidth)
{
  M2RTS_HALT (-1);
  __builtin_unreachable ();
  return static_cast<DynamicStrings_String> (NULL);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   doDecimalPlaces - returns a string which is accurate to
                     n decimal places.  It returns a new String
                     and, s, will be destroyed.
*/

static DynamicStrings_String doDecimalPlaces (DynamicStrings_String s, unsigned int n)
{
  int i;
  int l;
  int point;
  DynamicStrings_String t;
  DynamicStrings_String whole;
  DynamicStrings_String fraction;
  DynamicStrings_String tenths;
  DynamicStrings_String hundreths;

  l = DynamicStrings_Length (s);
  i = 0;
  /* remove '.'  */
  point = DynamicStrings_Index (s, '.', 0);
  if (point == 0)
    {
      s = DynamicStrings_Slice (DynamicStrings_Mark (s), 1, 0);
    }
  else if (point < l)
    {
      /* avoid dangling else.  */
      s = DynamicStrings_ConCat (DynamicStrings_Slice (DynamicStrings_Mark (s), 0, point), DynamicStrings_Mark (DynamicStrings_Slice (DynamicStrings_Mark (s), point+1, 0)));
    }
  else
    {
      /* avoid dangling else.  */
      s = DynamicStrings_Slice (DynamicStrings_Mark (s), 0, point);
    }
  l = DynamicStrings_Length (s);
  i = 0;
  if (l > 0)
    {
      /* skip over leading zeros  */
      while ((i < l) && ((DynamicStrings_char (s, i)) == '0'))
        {
          i += 1;
        }
      /* was the string full of zeros?  */
      if ((i == l) && ((DynamicStrings_char (s, i-1)) == '0'))
        {
          s = DynamicStrings_KillString (s);
          s = DynamicStrings_ConCat (DynamicStrings_InitString ((const char *) "0.", 2), DynamicStrings_Mark (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar ('0')), n)));
          return s;
        }
    }
  /* insert leading zero  */
  s = DynamicStrings_ConCat (DynamicStrings_InitStringChar ('0'), DynamicStrings_Mark (s));
  point += 1;  /* and move point position to correct place  */
  l = DynamicStrings_Length (s);  /* update new length  */
  i = point;  /* update new length  */
  while ((n > 1) && (i < l))
    {
      n -= 1;
      i += 1;
    }
  if ((i+3) <= l)
    {
      t = DynamicStrings_Dup (s);
      hundreths = DynamicStrings_Slice (DynamicStrings_Mark (s), i+1, i+3);
      s = t;
      if ((StringConvert_stoc (hundreths)) >= 50)
        {
          s = carryOne (DynamicStrings_Mark (s), static_cast<unsigned int> (i));
        }
      hundreths = DynamicStrings_KillString (hundreths);
    }
  else if ((i+2) <= l)
    {
      /* avoid dangling else.  */
      t = DynamicStrings_Dup (s);
      tenths = DynamicStrings_Slice (DynamicStrings_Mark (s), i+1, i+2);
      s = t;
      if ((StringConvert_stoc (tenths)) >= 5)
        {
          s = carryOne (DynamicStrings_Mark (s), static_cast<unsigned int> (i));
        }
      tenths = DynamicStrings_KillString (tenths);
    }
  /* check whether we need to remove the leading zero  */
  if ((DynamicStrings_char (s, 0)) == '0')
    {
      s = DynamicStrings_Slice (DynamicStrings_Mark (s), 1, 0);
      l -= 1;
      point -= 1;
    }
  if (i < l)
    {
      s = DynamicStrings_Slice (DynamicStrings_Mark (s), 0, i);
      l = DynamicStrings_Length (s);
      if (l < point)
        {
          s = DynamicStrings_ConCat (s, DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar ('0')), static_cast<unsigned int> (point-l)));
        }
    }
  /* re-insert the point  */
  if (point >= 0)
    {
      /* avoid gcc warning by using compound statement even if not strictly necessary.  */
      if (point == 0)
        {
          s = DynamicStrings_ConCat (DynamicStrings_InitStringChar ('.'), DynamicStrings_Mark (s));
        }
      else
        {
          s = DynamicStrings_ConCat (DynamicStrings_ConCatChar (DynamicStrings_Slice (DynamicStrings_Mark (s), 0, point), '.'), DynamicStrings_Mark (DynamicStrings_Slice (DynamicStrings_Mark (s), point, 0)));
        }
    }
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   doSigFig - returns a string which is accurate to
              n decimal places.  It returns a new String
              and, s, will be destroyed.
*/

static DynamicStrings_String doSigFig (DynamicStrings_String s, unsigned int n)
{
  int i;
  int l;
  int z;
  int point;
  DynamicStrings_String t;
  DynamicStrings_String tenths;
  DynamicStrings_String hundreths;

  l = DynamicStrings_Length (s);
  i = 0;
  /* remove '.'  */
  point = DynamicStrings_Index (s, '.', 0);
  if (point >= 0)
    {
      if (point == 0)
        {
          s = DynamicStrings_Slice (DynamicStrings_Mark (s), 1, 0);
        }
      else if (point < l)
        {
          /* avoid dangling else.  */
          s = DynamicStrings_ConCat (DynamicStrings_Slice (DynamicStrings_Mark (s), 0, point), DynamicStrings_Mark (DynamicStrings_Slice (DynamicStrings_Mark (s), point+1, 0)));
        }
      else
        {
          /* avoid dangling else.  */
          s = DynamicStrings_Slice (DynamicStrings_Mark (s), 0, point);
        }
    }
  else
    {
      s = DynamicStrings_Dup (DynamicStrings_Mark (s));
    }
  l = DynamicStrings_Length (s);
  i = 0;
  if (l > 0)
    {
      /* skip over leading zeros  */
      while ((i < l) && ((DynamicStrings_char (s, i)) == '0'))
        {
          i += 1;
        }
      /* was the string full of zeros?  */
      if ((i == l) && ((DynamicStrings_char (s, i-1)) == '0'))
        {
          /* truncate string  */
          s = DynamicStrings_Slice (DynamicStrings_Mark (s), 0, static_cast<int> (n));
          i = n;
        }
    }
  /* add a leading zero in case we need to overflow the carry  */
  z = i;  /* remember where we inserted zero  */
  if (z == 0)  /* remember where we inserted zero  */
    {
      s = DynamicStrings_ConCat (DynamicStrings_InitStringChar ('0'), DynamicStrings_Mark (s));
    }
  else
    {
      s = DynamicStrings_ConCat (DynamicStrings_ConCatChar (DynamicStrings_Slice (DynamicStrings_Mark (s), 0, i), '0'), DynamicStrings_Mark (DynamicStrings_Slice (DynamicStrings_Mark (s), i, 0)));
    }
  n += 1;  /* and increase the number of sig figs needed  */
  l = DynamicStrings_Length (s);  /* and increase the number of sig figs needed  */
  while ((n > 1) && (i < l))
    {
      n -= 1;
      i += 1;
    }
  if ((i+3) <= l)
    {
      t = DynamicStrings_Dup (s);
      hundreths = DynamicStrings_Slice (DynamicStrings_Mark (s), i+1, i+3);
      s = t;
      if ((StringConvert_stoc (hundreths)) >= 50)
        {
          s = carryOne (DynamicStrings_Mark (s), static_cast<unsigned int> (i));
        }
      hundreths = DynamicStrings_KillString (hundreths);
    }
  else if ((i+2) <= l)
    {
      /* avoid dangling else.  */
      t = DynamicStrings_Dup (s);
      tenths = DynamicStrings_Slice (DynamicStrings_Mark (s), i+1, i+2);
      s = t;
      if ((StringConvert_stoc (tenths)) >= 5)
        {
          s = carryOne (DynamicStrings_Mark (s), static_cast<unsigned int> (i));
        }
      tenths = DynamicStrings_KillString (tenths);
    }
  /* check whether we need to remove the leading zero  */
  if ((DynamicStrings_char (s, z)) == '0')
    {
      if (z == 0)
        {
          s = DynamicStrings_Slice (DynamicStrings_Mark (s), z+1, 0);
        }
      else
        {
          s = DynamicStrings_ConCat (DynamicStrings_Slice (DynamicStrings_Mark (s), 0, z), DynamicStrings_Mark (DynamicStrings_Slice (DynamicStrings_Mark (s), z+1, 0)));
        }
      l = DynamicStrings_Length (s);
    }
  else
    {
      point += 1;
    }
  if (i < l)
    {
      s = DynamicStrings_Slice (DynamicStrings_Mark (s), 0, i);
      l = DynamicStrings_Length (s);
      if (l < point)
        {
          s = DynamicStrings_ConCat (s, DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar ('0')), static_cast<unsigned int> (point-l)));
        }
    }
  /* re-insert the point  */
  if (point >= 0)
    {
      /* avoid gcc warning by using compound statement even if not strictly necessary.  */
      if (point == 0)
        {
          s = DynamicStrings_ConCat (DynamicStrings_InitStringChar ('.'), DynamicStrings_Mark (s));
        }
      else
        {
          s = DynamicStrings_ConCat (DynamicStrings_ConCatChar (DynamicStrings_Slice (DynamicStrings_Mark (s), 0, point), '.'), DynamicStrings_Mark (DynamicStrings_Slice (DynamicStrings_Mark (s), point, 0)));
        }
    }
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   carryOne - add a carry at position, i.
*/

static DynamicStrings_String carryOne (DynamicStrings_String s, unsigned int i)
{
  if (i >= 0)
    {
      if (IsDigit (DynamicStrings_char (s, static_cast<int> (i))))
        {
          /* avoid gcc warning by using compound statement even if not strictly necessary.  */
          if ((DynamicStrings_char (s, static_cast<int> (i))) == '9')
            {
              if (i == 0)
                {
                  s = DynamicStrings_ConCat (DynamicStrings_InitStringChar ('1'), DynamicStrings_Mark (s));
                  return s;
                }
              else
                {
                  s = DynamicStrings_ConCat (DynamicStrings_ConCatChar (DynamicStrings_Slice (DynamicStrings_Mark (s), 0, static_cast<int> (i)), '0'), DynamicStrings_Mark (DynamicStrings_Slice (DynamicStrings_Mark (s), static_cast<int> (i+1), 0)));
                  return carryOne (s, i-1);
                }
            }
          else
            {
              if (i == 0)
                {
                  s = DynamicStrings_ConCat (DynamicStrings_InitStringChar ( ((char) ( ((unsigned int) (DynamicStrings_char (s, static_cast<int> (i))))+1))), DynamicStrings_Mark (DynamicStrings_Slice (DynamicStrings_Mark (s), static_cast<int> (i+1), 0)));
                }
              else
                {
                  s = DynamicStrings_ConCat (DynamicStrings_ConCatChar (DynamicStrings_Slice (DynamicStrings_Mark (s), 0, static_cast<int> (i)), ((char) ( ((unsigned int) (DynamicStrings_char (s, static_cast<int> (i))))+1))), DynamicStrings_Mark (DynamicStrings_Slice (DynamicStrings_Mark (s), static_cast<int> (i+1), 0)));
                }
            }
        }
    }
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   IntegerToString - converts INTEGER, i, into a String. The field with can be specified
                     if non zero. Leading characters are defined by padding and this
                     function will prepend a + if sign is set to TRUE.
                     The base allows the caller to generate binary, octal, decimal, hexidecimal
                     numbers. The value of lower is only used when hexidecimal numbers are
                     generated and if TRUE then digits abcdef are used, and if FALSE then ABCDEF
                     are used.
*/

extern "C" DynamicStrings_String StringConvert_IntegerToString (int i, unsigned int width, char padding, bool sign, unsigned int base, bool lower)
{
  DynamicStrings_String s;
  unsigned int c;

  if (i < 0)
    {
      if (i == (INT_MIN))
        {
          /* remember that -15 MOD 4 = 1 in Modula-2  */
          c = ((unsigned int ) (abs (i+1)))+1;
          if (width > 0)
            {
              return DynamicStrings_ConCat (StringConvert_IntegerToString (-((int ) (c / base)), width-1, padding, sign, base, lower), DynamicStrings_Mark (StringConvert_IntegerToString (static_cast<int> (c % base), 0, ' ', false, base, lower)));
            }
          else
            {
              return DynamicStrings_ConCat (StringConvert_IntegerToString (-((int ) (c / base)), 0, padding, sign, base, lower), DynamicStrings_Mark (StringConvert_IntegerToString (static_cast<int> (c % base), 0, ' ', false, base, lower)));
            }
        }
      else
        {
          s = DynamicStrings_InitString ((const char *) "-", 1);
        }
      i = -i;
    }
  else
    {
      if (sign)
        {
          s = DynamicStrings_InitString ((const char *) "+", 1);
        }
      else
        {
          s = DynamicStrings_InitString ((const char *) "", 0);
        }
    }
  if (i > (((int ) (base))-1))
    {
      s = DynamicStrings_ConCat (DynamicStrings_ConCat (s, DynamicStrings_Mark (StringConvert_IntegerToString (static_cast<int> (((unsigned int ) (i)) / base), 0, ' ', false, base, lower))), DynamicStrings_Mark (StringConvert_IntegerToString (static_cast<int> (((unsigned int ) (i)) % base), 0, ' ', false, base, lower)));
    }
  else
    {
      if (i <= 9)
        {
          s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_InitStringChar ( ((char) (((unsigned int ) (i))+ ((unsigned int) ('0')))))));
        }
      else
        {
          if (lower)
            {
              s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_InitStringChar ( ((char) ((((unsigned int ) (i))+ ((unsigned int) ('a')))-10)))));
            }
          else
            {
              s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_InitStringChar ( ((char) ((((unsigned int ) (i))+ ((unsigned int) ('A')))-10)))));
            }
        }
    }
  if (width > (DynamicStrings_Length (s)))
    {
      return DynamicStrings_ConCat (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar (padding)), width-(DynamicStrings_Length (s))), DynamicStrings_Mark (s));
    }
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   CardinalToString - converts CARDINAL, c, into a String. The field with can be specified
                      if non zero. Leading characters are defined by padding.
                      The base allows the caller to generate binary, octal, decimal, hexidecimal
                      numbers. The value of lower is only used when hexidecimal numbers are
                      generated and if TRUE then digits abcdef are used, and if FALSE then ABCDEF
                      are used.
*/

extern "C" DynamicStrings_String StringConvert_CardinalToString (unsigned int c, unsigned int width, char padding, unsigned int base, bool lower)
{
  DynamicStrings_String s;

  s = DynamicStrings_InitString ((const char *) "", 0);
  if (c > (base-1))
    {
      s = DynamicStrings_ConCat (DynamicStrings_ConCat (s, DynamicStrings_Mark (StringConvert_CardinalToString (c / base, 0, ' ', base, lower))), DynamicStrings_Mark (StringConvert_CardinalToString (c % base, 0, ' ', base, lower)));
    }
  else
    {
      if (c <= 9)
        {
          s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_InitStringChar ( ((char) (c+ ((unsigned int) ('0')))))));
        }
      else
        {
          if (lower)
            {
              s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_InitStringChar ( ((char) ((c+ ((unsigned int) ('a')))-10)))));
            }
          else
            {
              s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_InitStringChar ( ((char) ((c+ ((unsigned int) ('A')))-10)))));
            }
        }
    }
  if (width > (DynamicStrings_Length (s)))
    {
      return DynamicStrings_ConCat (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar (padding)), width-(DynamicStrings_Length (s))), s);
    }
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   StringToInteger - converts a string, s, of, base, into an INTEGER.
                     Leading white space is ignored. It stops converting
                     when either the string is exhausted or if an illegal
                     numeral is found.
                     The parameter found is set TRUE if a number was found.
*/

extern "C" int StringConvert_StringToInteger (DynamicStrings_String s, unsigned int base, bool *found)
{
  unsigned int n;
  unsigned int l;
  unsigned int c;
  bool negative;

  s = DynamicStrings_RemoveWhitePrefix (s);  /* returns a new string, s  */
  l = DynamicStrings_Length (s);  /* returns a new string, s  */
  c = 0;
  n = 0;
  negative = false;
  if (n < l)
    {
      /* parse leading + and -  */
      while (((DynamicStrings_char (s, static_cast<int> (n))) == '-') || ((DynamicStrings_char (s, static_cast<int> (n))) == '+'))
        {
          if ((DynamicStrings_char (s, static_cast<int> (n))) == '-')
            {
              negative = ! negative;
            }
          n += 1;
        }
      while ((n < l) && ((IsDecimalDigitValid (DynamicStrings_char (s, static_cast<int> (n)), base, &c)) || (IsHexidecimalDigitValid (DynamicStrings_char (s, static_cast<int> (n)), base, &c))))
        {
          (*found) = true;
          n += 1;
        }
    }
  s = DynamicStrings_KillString (s);
  if (negative)
    {
      return -((int ) (Min (((unsigned int ) (INT_MAX))+1, c)));
    }
  else
    {
      return (int ) (Min (static_cast<unsigned int> (INT_MAX), c));
    }
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   StringToCardinal - converts a string, s, of, base, into a CARDINAL.
                      Leading white space is ignored. It stops converting
                      when either the string is exhausted or if an illegal
                      numeral is found.
                      The parameter found is set TRUE if a number was found.
*/

extern "C" unsigned int StringConvert_StringToCardinal (DynamicStrings_String s, unsigned int base, bool *found)
{
  unsigned int n;
  unsigned int l;
  unsigned int c;

  s = DynamicStrings_RemoveWhitePrefix (s);  /* returns a new string, s  */
  l = DynamicStrings_Length (s);  /* returns a new string, s  */
  c = 0;
  n = 0;
  if (n < l)
    {
      /* parse leading +  */
      while ((DynamicStrings_char (s, static_cast<int> (n))) == '+')
        {
          n += 1;
        }
      while ((n < l) && ((IsDecimalDigitValid (DynamicStrings_char (s, static_cast<int> (n)), base, &c)) || (IsHexidecimalDigitValid (DynamicStrings_char (s, static_cast<int> (n)), base, &c))))
        {
          (*found) = true;
          n += 1;
        }
    }
  s = DynamicStrings_KillString (s);
  return c;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   LongIntegerToString - converts LONGINT, i, into a String. The field with
                         can be specified if non zero. Leading characters
                         are defined by padding and this function will
                         prepend a + if sign is set to TRUE.
                         The base allows the caller to generate binary,
                         octal, decimal, hexidecimal numbers.
                         The value of lower is only used when hexidecimal
                         numbers are generated and if TRUE then digits
                         abcdef are used, and if FALSE then ABCDEF are used.
*/

extern "C" DynamicStrings_String StringConvert_LongIntegerToString (long int i, unsigned int width, char padding, bool sign, unsigned int base, bool lower)
{
  DynamicStrings_String s;
  long unsigned int c;

  if (i < 0)
    {
      if (i == (LONG_MIN))
        {
          /* remember that -15 MOD 4 is 1 in Modula-2, and although ABS(MIN(LONGINT)+1)
            is very likely MAX(LONGINT), it is safer not to assume this is the case  */
          c = ((long unsigned int ) (labs (i+1)))+1;
          if (width > 0)
            {
              return DynamicStrings_ConCat (StringConvert_LongIntegerToString (-((long int ) (c / ((long unsigned int ) (base)))), width-1, padding, sign, base, lower), DynamicStrings_Mark (StringConvert_LongIntegerToString (static_cast<long int> (c % ((long unsigned int ) (base))), 0, ' ', false, base, lower)));
            }
          else
            {
              return DynamicStrings_ConCat (StringConvert_LongIntegerToString (-((long int ) (c / ((long unsigned int ) (base)))), 0, padding, sign, base, lower), DynamicStrings_Mark (StringConvert_LongIntegerToString (static_cast<long int> (c % ((long unsigned int ) (base))), 0, ' ', false, base, lower)));
            }
        }
      else
        {
          s = DynamicStrings_InitString ((const char *) "-", 1);
        }
      i = -i;
    }
  else
    {
      if (sign)
        {
          s = DynamicStrings_InitString ((const char *) "+", 1);
        }
      else
        {
          s = DynamicStrings_InitString ((const char *) "", 0);
        }
    }
  if (i > ((long int ) (base-1)))
    {
      s = DynamicStrings_ConCat (DynamicStrings_ConCat (s, DynamicStrings_Mark (StringConvert_LongIntegerToString (i / ((long int ) (base)), 0, ' ', false, base, lower))), DynamicStrings_Mark (StringConvert_LongIntegerToString (i % ((long int ) (base)), 0, ' ', false, base, lower)));
    }
  else
    {
      if (i <= 9)
        {
          s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_InitStringChar ( ((char) (((unsigned int ) (i))+ ((unsigned int) ('0')))))));
        }
      else
        {
          if (lower)
            {
              s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_InitStringChar ( ((char) ((((unsigned int ) (i))+ ((unsigned int) ('a')))-10)))));
            }
          else
            {
              s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_InitStringChar ( ((char) ((((unsigned int ) (i))+ ((unsigned int) ('A')))-10)))));
            }
        }
    }
  if (width > (DynamicStrings_Length (s)))
    {
      return DynamicStrings_ConCat (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar (padding)), width-(DynamicStrings_Length (s))), s);
    }
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   StringToLongInteger - converts a string, s, of, base, into an LONGINT.
                         Leading white space is ignored. It stops converting
                         when either the string is exhausted or if an illegal
                         numeral is found.
                         The parameter found is set TRUE if a number was found.
*/

extern "C" long int StringConvert_StringToLongInteger (DynamicStrings_String s, unsigned int base, bool *found)
{
  unsigned int n;
  unsigned int l;
  long unsigned int c;
  bool negative;

  s = DynamicStrings_RemoveWhitePrefix (s);  /* returns a new string, s  */
  l = DynamicStrings_Length (s);  /* returns a new string, s  */
  c = 0;
  n = 0;
  negative = false;
  if (n < l)
    {
      /* parse leading + and -  */
      while (((DynamicStrings_char (s, static_cast<int> (n))) == '-') || ((DynamicStrings_char (s, static_cast<int> (n))) == '+'))
        {
          if ((DynamicStrings_char (s, static_cast<int> (n))) == '-')
            {
              negative = ! negative;
            }
          n += 1;
        }
      while ((n < l) && ((IsDecimalDigitValidLong (DynamicStrings_char (s, static_cast<int> (n)), base, &c)) || (IsHexidecimalDigitValidLong (DynamicStrings_char (s, static_cast<int> (n)), base, &c))))
        {
          (*found) = true;
          n += 1;
        }
    }
  s = DynamicStrings_KillString (s);
  if (negative)
    {
      return -((long int ) (LongMin (((long unsigned int ) (LONG_MAX))+1, c)));
    }
  else
    {
      return (long int ) (LongMin (static_cast<long unsigned int> (LONG_MAX), c));
    }
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   LongCardinalToString - converts LONGCARD, c, into a String. The field
                          width can be specified if non zero. Leading
                          characters are defined by padding.
                          The base allows the caller to generate binary,
                          octal, decimal, hexidecimal numbers.
                          The value of lower is only used when hexidecimal
                          numbers are generated and if TRUE then digits
                          abcdef are used, and if FALSE then ABCDEF are used.
*/

extern "C" DynamicStrings_String StringConvert_LongCardinalToString (long unsigned int c, unsigned int width, char padding, unsigned int base, bool lower)
{
  DynamicStrings_String s;

  s = DynamicStrings_InitString ((const char *) "", 0);
  if (c > ((long unsigned int ) (base-1)))
    {
      s = DynamicStrings_ConCat (DynamicStrings_ConCat (s, StringConvert_LongCardinalToString (c / ((long unsigned int ) (base)), 0, ' ', base, lower)), StringConvert_LongCardinalToString (c % ((long unsigned int ) (base)), 0, ' ', base, lower));
    }
  else
    {
      if (c <= 9)
        {
          s = DynamicStrings_ConCat (s, DynamicStrings_InitStringChar ( ((char) (((unsigned int ) (c))+ ((unsigned int) ('0'))))));
        }
      else
        {
          if (lower)
            {
              s = DynamicStrings_ConCat (s, DynamicStrings_InitStringChar ( ((char) ((((unsigned int ) (c))+ ((unsigned int) ('a')))-10))));
            }
          else
            {
              s = DynamicStrings_ConCat (s, DynamicStrings_InitStringChar ( ((char) ((((unsigned int ) (c))+ ((unsigned int) ('A')))-10))));
            }
        }
    }
  if (width > (DynamicStrings_Length (s)))
    {
      return DynamicStrings_ConCat (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar (padding)), width-(DynamicStrings_Length (s))), s);
    }
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   StringToLongCardinal - converts a string, s, of, base, into a LONGCARD.
                          Leading white space is ignored. It stops converting
                          when either the string is exhausted or if an illegal
                          numeral is found.
                          The parameter found is set TRUE if a number was found.
*/

extern "C" long unsigned int StringConvert_StringToLongCardinal (DynamicStrings_String s, unsigned int base, bool *found)
{
  unsigned int n;
  unsigned int l;
  long unsigned int c;

  s = DynamicStrings_RemoveWhitePrefix (s);  /* returns a new string, s  */
  l = DynamicStrings_Length (s);  /* returns a new string, s  */
  c = 0;
  n = 0;
  if (n < l)
    {
      /* parse leading +  */
      while ((DynamicStrings_char (s, static_cast<int> (n))) == '+')
        {
          n += 1;
        }
      while ((n < l) && ((IsDecimalDigitValidLong (DynamicStrings_char (s, static_cast<int> (n)), base, &c)) || (IsHexidecimalDigitValidLong (DynamicStrings_char (s, static_cast<int> (n)), base, &c))))
        {
          (*found) = true;
          n += 1;
        }
    }
  s = DynamicStrings_KillString (s);
  return c;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   ShortCardinalToString - converts SHORTCARD, c, into a String. The field
                          width can be specified if non zero. Leading
                          characters are defined by padding.
                          The base allows the caller to generate binary,
                          octal, decimal, hexidecimal numbers.
                          The value of lower is only used when hexidecimal
                          numbers are generated and if TRUE then digits
                          abcdef are used, and if FALSE then ABCDEF are used.
*/

extern "C" DynamicStrings_String StringConvert_ShortCardinalToString (short unsigned int c, unsigned int width, char padding, unsigned int base, bool lower)
{
  DynamicStrings_String s;

  s = DynamicStrings_InitString ((const char *) "", 0);
  if (((unsigned int ) (c)) > (base-1))
    {
      s = DynamicStrings_ConCat (DynamicStrings_ConCat (s, StringConvert_ShortCardinalToString (c / ((short unsigned int ) (base)), 0, ' ', base, lower)), StringConvert_ShortCardinalToString (c % ((short unsigned int ) (base)), 0, ' ', base, lower));
    }
  else
    {
      if (c <= 9)
        {
          s = DynamicStrings_ConCat (s, DynamicStrings_InitStringChar ( ((char) (((unsigned int ) (c))+ ((unsigned int) ('0'))))));
        }
      else
        {
          if (lower)
            {
              s = DynamicStrings_ConCat (s, DynamicStrings_InitStringChar ( ((char) ((((unsigned int ) (c))+ ((unsigned int) ('a')))-10))));
            }
          else
            {
              s = DynamicStrings_ConCat (s, DynamicStrings_InitStringChar ( ((char) ((((unsigned int ) (c))+ ((unsigned int) ('A')))-10))));
            }
        }
    }
  if (width > (DynamicStrings_Length (s)))
    {
      return DynamicStrings_ConCat (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar (padding)), width-(DynamicStrings_Length (s))), s);
    }
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   StringToShortCardinal - converts a string, s, of, base, into a SHORTCARD.
                           Leading white space is ignored. It stops converting
                           when either the string is exhausted or if an illegal
                           numeral is found.
                           The parameter found is set TRUE if a number was found.
*/

extern "C" short unsigned int StringConvert_StringToShortCardinal (DynamicStrings_String s, unsigned int base, bool *found)
{
  unsigned int n;
  unsigned int l;
  short unsigned int c;

  s = DynamicStrings_RemoveWhitePrefix (s);  /* returns a new string, s  */
  l = DynamicStrings_Length (s);  /* returns a new string, s  */
  c = 0;
  n = 0;
  if (n < l)
    {
      /* parse leading +  */
      while ((DynamicStrings_char (s, static_cast<int> (n))) == '+')
        {
          n += 1;
        }
      while ((n < l) && ((IsDecimalDigitValidShort (DynamicStrings_char (s, static_cast<int> (n)), base, &c)) || (IsHexidecimalDigitValidShort (DynamicStrings_char (s, static_cast<int> (n)), base, &c))))
        {
          (*found) = true;
          n += 1;
        }
    }
  s = DynamicStrings_KillString (s);
  return c;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   stoi - decimal string to INTEGER
*/

extern "C" int StringConvert_stoi (DynamicStrings_String s)
{
  bool found;

  return StringConvert_StringToInteger (s, 10, &found);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   itos - integer to decimal string.
*/

extern "C" DynamicStrings_String StringConvert_itos (int i, unsigned int width, char padding, bool sign)
{
  return StringConvert_IntegerToString (i, width, padding, sign, 10, false);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   ctos - cardinal to decimal string.
*/

extern "C" DynamicStrings_String StringConvert_ctos (unsigned int c, unsigned int width, char padding)
{
  return StringConvert_CardinalToString (c, width, padding, 10, false);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   stoc - decimal string to CARDINAL
*/

extern "C" unsigned int StringConvert_stoc (DynamicStrings_String s)
{
  bool found;

  return StringConvert_StringToCardinal (s, 10, &found);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   hstoi - hexidecimal string to INTEGER
*/

extern "C" int StringConvert_hstoi (DynamicStrings_String s)
{
  bool found;

  return StringConvert_StringToInteger (s, 16, &found);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   ostoi - octal string to INTEGER
*/

extern "C" int StringConvert_ostoi (DynamicStrings_String s)
{
  bool found;

  return StringConvert_StringToInteger (s, 8, &found);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   bstoi - binary string to INTEGER
*/

extern "C" int StringConvert_bstoi (DynamicStrings_String s)
{
  bool found;

  return StringConvert_StringToInteger (s, 2, &found);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   hstoc - hexidecimal string to CARDINAL
*/

extern "C" unsigned int StringConvert_hstoc (DynamicStrings_String s)
{
  bool found;

  return StringConvert_StringToCardinal (s, 16, &found);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   ostoc - octal string to CARDINAL
*/

extern "C" unsigned int StringConvert_ostoc (DynamicStrings_String s)
{
  bool found;

  return StringConvert_StringToCardinal (s, 8, &found);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   bstoc - binary string to CARDINAL
*/

extern "C" unsigned int StringConvert_bstoc (DynamicStrings_String s)
{
  bool found;

  return StringConvert_StringToCardinal (s, 2, &found);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   StringToLongreal - returns a LONGREAL and sets found to TRUE if a legal number is seen.
*/

extern "C" long double StringConvert_StringToLongreal (DynamicStrings_String s, bool *found)
{
  bool error;
  long double value;

  s = DynamicStrings_RemoveWhitePrefix (s);  /* new string is created  */
  value = ldtoa_strtold (DynamicStrings_string (s), &error);  /* new string is created  */
  s = DynamicStrings_KillString (s);
  (*found) = ! error;
  return value;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   LongrealToString - converts a LONGREAL number, Real, which has,
                      TotalWidth, and FractionWidth into a string.
                      It uses decimal notation.

                      So for example:

                      LongrealToString(1.0, 4, 2)  -> '1.00'
                      LongrealToString(12.3, 5, 2) -> '12.30'
                      LongrealToString(12.3, 6, 2) -> ' 12.30'
                      LongrealToString(12.3, 6, 3) -> '12.300'

                      if total width is too small then the fraction
                      becomes truncated.

                      LongrealToString(12.3, 5, 3) -> '12.30'

                      Positive numbers do not have a '+' prepended.
                      Negative numbers will have a '-' prepended and
                      the TotalWidth will need to be large enough
                      to contain the sign, whole number, '.' and
                      fractional components.
*/

extern "C" DynamicStrings_String StringConvert_LongrealToString (long double x, unsigned int TotalWidth, unsigned int FractionWidth)
{
  bool maxprecision;
  DynamicStrings_String s;
  void * r;
  int point;
  bool sign;
  int l;

  if (TotalWidth == 0)
    {
      maxprecision = true;
      r = ldtoa_ldtoa (x, ldtoa_decimaldigits, 100, &point, &sign);
    }
  else
    {
      r = ldtoa_ldtoa (x, ldtoa_decimaldigits, 100, &point, &sign);
    }
  s = DynamicStrings_InitStringCharStar (r);
  libc_free (r);
  l = DynamicStrings_Length (s);
  if (point > l)
    {
      /* avoid dangling else.  */
      s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar ('0')), static_cast<unsigned int> (point-l))));
      s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_InitString ((const char *) ".0", 2)));
      if (! maxprecision && (FractionWidth > 0))
        {
          FractionWidth -= 1;
          if (((int ) (FractionWidth)) > (point-l))
            {
              s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "0", 1)), FractionWidth)));
            }
        }
    }
  else if (point < 0)
    {
      /* avoid dangling else.  */
      s = DynamicStrings_ConCat (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar ('0')), static_cast<unsigned int> (-point)), DynamicStrings_Mark (s));
      l = DynamicStrings_Length (s);
      s = DynamicStrings_ConCat (DynamicStrings_InitString ((const char *) "0.", 2), DynamicStrings_Mark (s));
      if (! maxprecision && (l < ((int ) (FractionWidth))))
        {
          s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "0", 1)), static_cast<unsigned int> (((int ) (FractionWidth))-l))));
        }
    }
  else
    {
      /* avoid dangling else.  */
      if (point == 0)
        {
          s = DynamicStrings_ConCat (DynamicStrings_InitString ((const char *) "0.", 2), DynamicStrings_Mark (DynamicStrings_Slice (DynamicStrings_Mark (s), point, 0)));
        }
      else
        {
          s = DynamicStrings_ConCat (DynamicStrings_ConCatChar (DynamicStrings_Slice (DynamicStrings_Mark (s), 0, point), '.'), DynamicStrings_Mark (DynamicStrings_Slice (DynamicStrings_Mark (s), point, 0)));
        }
      if (! maxprecision && ((l-point) < ((int ) (FractionWidth))))
        {
          s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "0", 1)), static_cast<unsigned int> (((int ) (FractionWidth))-(l-point)))));
        }
    }
  if ((DynamicStrings_Length (s)) > TotalWidth)
    {
      /* avoid gcc warning by using compound statement even if not strictly necessary.  */
      if (TotalWidth > 0)
        {
          if (sign)
            {
              s = DynamicStrings_Slice (DynamicStrings_Mark (StringConvert_ToDecimalPlaces (s, FractionWidth)), 0, static_cast<int> (TotalWidth-1));
              s = DynamicStrings_ConCat (DynamicStrings_InitStringChar ('-'), DynamicStrings_Mark (s));
              sign = false;
            }
          else
            {
              /* minus 1 because all results will include a '.'  */
              s = DynamicStrings_Slice (DynamicStrings_Mark (StringConvert_ToDecimalPlaces (s, FractionWidth)), 0, static_cast<int> (TotalWidth));
            }
        }
      else
        {
          if (sign)
            {
              s = StringConvert_ToDecimalPlaces (s, FractionWidth);
              s = DynamicStrings_ConCat (DynamicStrings_InitStringChar ('-'), DynamicStrings_Mark (s));
              sign = false;
            }
          else
            {
              /* minus 1 because all results will include a '.'  */
              s = StringConvert_ToDecimalPlaces (s, FractionWidth);
            }
        }
    }
  if ((DynamicStrings_Length (s)) < TotalWidth)
    {
      s = DynamicStrings_ConCat (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar (' ')), TotalWidth-(DynamicStrings_Length (s))), DynamicStrings_Mark (s));
    }
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   stor - returns a REAL given a string.
*/

extern "C" double StringConvert_stor (DynamicStrings_String s)
{
  bool found;

  return (double ) (StringConvert_StringToLongreal (s, &found));
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   stolr - returns a LONGREAL given a string.
*/

extern "C" long double StringConvert_stolr (DynamicStrings_String s)
{
  bool found;

  return StringConvert_StringToLongreal (s, &found);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   ToSigFig - returns a floating point or base 10 integer
              string which is accurate to, n, significant
              figures.  It will return a new String
              and, s, will be destroyed.


              So:  12.345

              rounded to the following significant figures yields

              5      12.345
              4      12.34
              3      12.3
              2      12
              1      10
*/

extern "C" DynamicStrings_String StringConvert_ToSigFig (DynamicStrings_String s, unsigned int n)
{
  int point;
  unsigned int poTen;

  Assert ((IsDigit (DynamicStrings_char (s, 0))) || ((DynamicStrings_char (s, 0)) == '.'), (const char *) "../../gcc-read-write/gcc/m2/gm2-libs/StringConvert.mod", 54, 1222, (const char *) "ToSigFig", 8);
  point = DynamicStrings_Index (s, '.', 0);
  if (point < 0)
    {
      poTen = DynamicStrings_Length (s);
    }
  else
    {
      poTen = point;
    }
  s = doSigFig (s, n);
  /* if the last character is '.' remove it  */
  if (((DynamicStrings_Length (s)) > 0) && ((DynamicStrings_char (s, -1)) == '.'))
    {
      return DynamicStrings_Slice (DynamicStrings_Mark (s), 0, -1);
    }
  else
    {
      if (poTen > (DynamicStrings_Length (s)))
        {
          s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar ('0')), poTen-(DynamicStrings_Length (s)))));
        }
      return s;
    }
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   ToDecimalPlaces - returns a floating point or base 10 integer
                     string which is accurate to, n, decimal
                     places.  It will return a new String
                     and, s, will be destroyed.
                     Decimal places yields, n, digits after
                     the .

                     So:  12.345

                     rounded to the following decimal places yields

                     5      12.34500
                     4      12.3450
                     3      12.345
                     2      12.34
                     1      12.3
*/

extern "C" DynamicStrings_String StringConvert_ToDecimalPlaces (DynamicStrings_String s, unsigned int n)
{
  int point;

  Assert ((IsDigit (DynamicStrings_char (s, 0))) || ((DynamicStrings_char (s, 0)) == '.'), (const char *) "../../gcc-read-write/gcc/m2/gm2-libs/StringConvert.mod", 54, 1069, (const char *) "ToDecimalPlaces", 15);
  point = DynamicStrings_Index (s, '.', 0);
  if (point < 0)
    {
      /* avoid gcc warning by using compound statement even if not strictly necessary.  */
      if (n > 0)
        {
          return DynamicStrings_ConCat (DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_InitStringChar ('.'))), DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar ('0')), n));
        }
      else
        {
          return s;
        }
    }
  s = doDecimalPlaces (s, n);
  /* if the last character is '.' remove it  */
  if (((DynamicStrings_Length (s)) > 0) && ((DynamicStrings_char (s, -1)) == '.'))
    {
      return DynamicStrings_Slice (DynamicStrings_Mark (s), 0, -1);
    }
  else
    {
      return s;
    }
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}

extern "C" void _M2_StringConvert_init (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[])
{
}

extern "C" void _M2_StringConvert_fini (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[])
{
}
